package com.openatc.optimize.fixedtimeplan.config.cross;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

/**
 * @author mz
 * @version 1.0
 * @date 2021/11/3 15:47
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class Barrier {
    private int num;
    private List<BarrierItem> items;
    private double y;
    private long duration;

    public void adjustPhaseDuration(Map<Integer, Phase> phaseMap){
        boolean adjusted = false;
        /**
         * 设置最大最小绿
         * */
        for(BarrierItem barrierItem: items){

            for(Integer id : barrierItem.getData()){
                if(phaseMap.get(id).getDuration() < phaseMap.get(id).getMingreen()){
                    phaseMap.get(id).setDuration(phaseMap.get(id).getMingreen());
                    phaseMap.get(id).setAdjusted(true);
                    barrierItem.setAdjusted(true);
                    adjusted = true;
                }else if(phaseMap.get(id).getDuration() > phaseMap.get(id).getMaxgreen()){
                    phaseMap.get(id).setDuration(phaseMap.get(id).getMaxgreen());
                    phaseMap.get(id).setAdjusted(true);
                    barrierItem.setAdjusted(true);
                    adjusted = true;
                }
            }
        }


        if(!adjusted){
            return;
        }
        /**
         * 重新计算barrier长度
         * */
        int newduration = 0 ;
        for(BarrierItem barrierItem: items){
            int tempduration = 0;
            for(Integer id : barrierItem.getData()){
                tempduration += phaseMap.get(id).getDuration();
            }
            barrierItem.setDuration(tempduration);
            if(tempduration > newduration){
                newduration = tempduration;
            }
        }

        log.info("new duration of barrier:{} is {}",num, newduration);



        /**
         * 重新计算相位长度
         * */
        for(BarrierItem item:items){
            List<Integer> ids = item.getData();
            if(!item.isAdjusted()){

                double tempY = 0;
                for(Integer id : ids){
                    tempY += phaseMap.get(id).Y();
                }

                int temptotalduration = 0;
                for(int i = 0; i< ids.size(); i++){
                    int id = ids.get(i);
                    if(i != ids.size() - 1){

                        long phaseduration = Math.round(newduration * phaseMap.get(id).Y()/tempY);
                        temptotalduration += phaseduration;
                        phaseMap.get(id).setDuration(phaseduration);
                    }else{
                        phaseMap.get(id).setDuration(newduration - temptotalduration);
                    }
                }

            }else{
                int temptotalduration = 0;
                for(int i = 0; i< ids.size(); i++){
                    int id = ids.get(i);
                    if(i != ids.size() - 1){
                        if(!phaseMap.get(id).isAdjusted()){
                            long diff = newduration - item.getDuration();
                            log.info("phase:{}, item.getDuration():{}", item.getData(), item.getDuration());
                            log.info("diff of phase:{} is :{} ", item.getData(), diff);
                            long curduration = phaseMap.get(id).getDuration();
                            phaseMap.get(id).setDuration(curduration + diff);
                            log.info("phase:{}, old duration:{}, new duration:{}", id, curduration,curduration + diff );
                        }
                        temptotalduration += phaseMap.get(id).getDuration();
                    }else{
                        phaseMap.get(id).setDuration(newduration - temptotalduration);
                    }

                }


            }
            for(int id:ids){
                log.info("after adjusted phase:{}, duration:{}", id,phaseMap.get(id).getDuration() );
            }



        }

        duration = newduration;



    }



}
